using CommunityToolkit.Mvvm.ComponentModel; // 用于 MVVM 模型视图分离模式
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging.Messages;
using ICSharpCode.AvalonEdit;
using LuaConsole;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using NLua;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.IO;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Windows.Input;
using System.Windows.Threading;
using 雷赛板卡上位机.Models;
using 雷赛板卡上位机.Utilities;


namespace 雷赛板卡上位机.ViewModel;

public partial class InputTextBoxViewModel : BaseViewModel, IDisposable
{
    private readonly ILogger<InputTextBoxViewModel> logger;
    private readonly object _lock = new object();
    private readonly IConfiguration configuration;
    private readonly LuaMaster lua; // 创建一个 Lua 脚本执行器实例
    private readonly StringBuilder outTextBuffer = new(1024 * 8 * 8);
    private readonly Dispatcher _dispatcher;
    private DispatcherTimer _outputTimer;
    private CancellationTokenSource cancellationTokenSource;
    private Task task;
    private string luaPath;
    private double lineNums = 0;

    [ObservableProperty] string text; // 绑定到文本框的初始文本
    [ObservableProperty] string outText = string.Empty; // 存储要执行的 Lua 脚本
    [ObservableProperty] bool isEnable = true;

    public InputTextBoxViewModel(ILogger<InputTextBoxViewModel> logger, IConfiguration configuration, LuaMaster lua, Dispatcher dispatcher)
    {
        this.logger = logger;
        this.configuration = configuration;
        this.lua = lua;
        this._dispatcher = dispatcher;
        luaPath = this.configuration.GetRequiredSection("LuaPath").Value;
        if (File.Exists(Path.Combine(luaPath, "hello.lua")))
        {
            Text = File.ReadAllText(Path.Combine(luaPath, "hello.lua"));
        }
        LuaMasterExtension.lua = lua;
        LuaMasterExtension.LuaPath = luaPath;
        lua.AddClass();
        lua.AddFunction();
        //LuaMaster.PrintMsgAsync = AddTextAsync;
        LuaMaster.PrintMsg = AddText;
        LuaMaster.ClearMeg = ClearText;
        _outputTimer = new DispatcherTimer(DispatcherPriority.DataBind);
        _outputTimer.Interval = new TimeSpan(0, 0, 0, 0, 32);
        _outputTimer.Tick += (s, e) => UpdateOutput(s);
        _outputTimer.Start();
    }


    [RelayCommand]
    void Folding(object s)
    {
        //var text = s as TextEditor;
        //if (text != null)
        //{
        //    var folding = new EditorFoldingService();
        //    folding.Attach(text);
        //}
    }

    [RelayCommand]
    void MouseWhell(object s)
    {
        if (s is object[] a)
        {
            var text = a[0] as TextEditor;
            var e = a[1] as MouseWheelEventArgs;

            var next = text.ExtentHeight / text.FontSize;
            var max = text.ExtentHeight;
            switch (e.Delta)
            {
                case > 0:
                    text.ScrollToVerticalOffset(lineNums = lineNums - next <= 0 ? 0 : lineNums - next);
                    break;
                case < 0:
                    text.ScrollToVerticalOffset(lineNums = lineNums + next >= max ? max : lineNums + next);
                    break;
            }
        }

    }

    [RelayCommand]
    void Start()
    {
        lock (_lock) { outTextBuffer.Clear(); }
        //outTextBuffer.Clear();
        OutText = outTextBuffer.ToString();
        lua.IsExe = true; // 设置 Lua 脚本执行器为可执行状态
        IsEnable = false;
        if (task is not null && task.Status is TaskStatus.Running) { return; }

        cancellationTokenSource = new CancellationTokenSource(); // 创建取消令牌源

        task = new Task(() =>
        {
            try
            {
                lua.Master.DoString(Text); // 执行 Lua 脚本
            }
            catch (Exception e)
            {
                AddText($"Error:{e.Message}");
                logger.LogError(e.Message);
            }
            finally
            {
                IsEnable = true;
            }
        }, cancellationTokenSource.Token); // 使用取消令牌

        task.Start(); // 启动任务
    }

    [RelayCommand]
    void Stop()
    {
        if (IsEnable is true) return;
        IsEnable = true;
        lua.IsExe = false;
        if (cancellationTokenSource is not null)
        {
            if (!cancellationTokenSource.IsCancellationRequested)
            {
                cancellationTokenSource?.Cancel(); // 取消当前的取消令牌源
            }
        }
        Task.WaitAny(task);
        cancellationTokenSource?.Dispose(); // 清理取消令牌源资源
        task?.Dispose();
    }

    private void UpdateOutput(object? state)
    {
        lock (_lock)
        {
            OutText = outTextBuffer.ToString();
        }
    }
    public override void AddText(object sender)
    {
        string text;
        switch (sender)
        {
            case Array array:
                StringBuilder sb = new StringBuilder(array.Length + 1);
                foreach (var t in array)
                {
                    sb.Append(t.ToString());
                    sb.Append(" ");
                }
                text = sb.ToString();
                break;
            case null: text = "null"; break;
            case LuaTable luaTable:
                var pageSize = 100;
                var count = 0;
                int max = 50;
                StringBuilder xsb = new StringBuilder();
                foreach (KeyValuePair<object, object> keyValue in luaTable)
                {
                    if (++count % pageSize == 0)
                    {
                        Thread.Sleep(1);
                    }
                    if (keyValue.Key?.ToString() == "(temporary)")
                    {
                        continue;
                    }
                    var key = keyValue.Key.ToString();
                    xsb.Append(key);
                    xsb.Append(" : ");
                    var value = keyValue.Value?.ToString();
                    xsb.Append(value.Replace(" ", ""));
                    xsb.AppendLine();
                }
                text = xsb.ToString();
                break;
            default:
                Type type = sender.GetType();
                if (type.IsClass && type.Name.ToLower() != "string")
                {
                    StringBuilder builder = new StringBuilder();
                    foreach (var member in type.GetMembers())
                    {
                        builder.Append(member.MemberType.ToString());
                        builder.Append(" ");
                        builder.Append(type.Name);
                        builder.Append(".");
                        builder.Append(member.Name);
                        builder.AppendLine();
                    }
                    text = builder.ToString();
                }
                else
                {
                    text = sender.ToString();

                }
                break;
        }
        lock (_lock)
        {
            outTextBuffer.AppendLine(text);
        }
    }

    public override void ClearText(object str)
    {
        lock (_lock) { outTextBuffer.Clear(); }

        OutText = "";
    }
    private void ClearText()
    {
        this.ClearText(null);
    }
    public void Dispose()
    {
        lua.IsExe = false; // 设置 Lua 脚本执行器为非可执行状态
        if (cancellationTokenSource is not null)
        {
            if (!cancellationTokenSource.IsCancellationRequested)
            {
                cancellationTokenSource?.Cancel(); // 取消取消令牌源
            }
        }
        cancellationTokenSource?.Dispose(); // 再次清理取消令牌源资源
        _outputTimer?.Stop();
        _outputTimer?.Dispose();
        lua.Dispose(); // 关闭 Lua 脚本执行器
    }

    protected override void OnActivated()
    {
        Messenger.Register<InputTextBoxViewModel, ValueChangedMessage<bool>, string>(this, "MenuClose", (r, m) =>
        {
            if (m.Value)
            {
                r.Dispose();
            }
        });
    }
}